package com.schoolcloud.social.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.schoolcloud.api.client.front.FrontUserClient;
import com.schoolcloud.common.model.UserInfo;
import com.schoolcloud.common.exception.LoginUserException;
import com.schoolcloud.common.model.PageDTO;
import com.schoolcloud.common.model.R;
import com.schoolcloud.common.util.PageUtil;
import com.schoolcloud.common.util.UserContext;
import com.schoolcloud.social.dto.SocPostCreateDTO;
import com.schoolcloud.social.dto.SocPostReplyDTO;
import com.schoolcloud.social.entity.*;
import com.schoolcloud.social.query.BardQuery;
import com.schoolcloud.social.query.UserForumQuery;
import com.schoolcloud.social.query.PostQuery;
import com.schoolcloud.social.query.PostRepliesQuery;
import com.schoolcloud.social.service.*;
import com.schoolcloud.social.vo.*;
import com.schoolcolud.daomybatisplus.dto.MpPageUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class PostInteractionServiceImpl implements PostInteractionService {
    private final FrontUserClient frontClient;
    private final SocPostService postService;
    private final SocPostTagsService tagsService;
    private final SocPostTagRelationsService postTagService;
    private final SocBardService bardService;
    private final SocPostFileService postFileService;
    private final SocPostLikesService postLikesService;
    private final SocBardFollowService bardFollowService;
    private final SocPostRepliesService socPostRepliesService;
    private final SocPostRepliesFileService postRepliesFileService;
    private final UserForumProfilesService userForumProfilesService;

    @Override
    @Transactional
    public void addPost(SocPostCreateDTO socPost) {
//        用户如果是第一次发布， 则创建扩展用户数据
        UserForumProfiles userForumProfiles = userForumProfilesService.getByUserId(UserContext.getUserToInteger());
        if (userForumProfiles == null) {
            userForumProfiles = new UserForumProfiles();
            userForumProfiles.setUserId(UserContext.getUserToInteger());
            userForumProfiles.setPostCount(0);
            userForumProfiles.setExperience(0);
            userForumProfilesService.save(userForumProfiles);
        }
        socPost.setCreateTime(new Date());
        socPost.setUserId(UserContext.getUser());
        List<SocPostFile> uploadFileList = socPost.getUploadFileList();
        List<SocPostTags> tagList = socPost.getTags();
        postService.save(socPost);
//        保存上传的文件信息
        if (CollUtil.isNotEmpty(uploadFileList)) {
            uploadFileList.forEach(item -> {
                item.setPostId(socPost.getPostId());
                postFileService.save(item);
            });
        }
//        保存话题信息
        if (CollUtil.isNotEmpty(tagList)) {
            tagList.forEach(item -> {
                SocPostTagRelations socPostTag = new SocPostTagRelations();
                if (item.getTagId() != null) {
//                    如果该标签已经存在，那么就只只需要在关联表中插入即可
                    socPostTag.setTagId(item.getTagId());
                } else {
//                    否则先在标签表中插入对应的记录，然后再执行插入关联表中
                    SocPostTags socTags = new SocPostTags();
                    socTags.setTagName(item.getTagName());
                    socTags.setCreateTime(LocalDateTime.now());
                    tagsService.save(socTags);
                    socPostTag.setTagId(socTags.getTagId());
                }
                socPostTag.setPostId(socPost.getPostId());
                postTagService.save(socPostTag);
            });
        }
        userForumProfiles.setPostCount(userForumProfiles.getPostCount() + 1);
        userForumProfiles.setExperience(userForumProfiles.getExperience() + 10);//todo 从配置文件中获取
        userForumProfilesService.updateById(userForumProfiles);
    }

    @Override
    public PageDTO<SocPostItemVO> getPostItemVOPage(PostQuery query) {
        PageDTO<SocPost> postPage = postService.getPostPage(query);
        PageDTO<SocPostItemVO> dto = PageUtil.of(postPage, SocPostItemVO.class);
//        封装用户信息，图片信息,点赞数，评论数，登录人是否点赞
        if (CollUtil.isNotEmpty(dto.getList())) {
            List<SocPostItemVO> collect = dto.getList().stream().map(this::getSocPostItemVOBySoPost).toList();
            dto.setList(collect);
        }
        return dto;
    }

    @Override
    public SocPostInfoVO getPostInfo(PostRepliesQuery query) {
//        获取基本信息
        SocPost byId = postService.getById(query.getPostId());
        if (byId == null) {
            return null;
        }
        SocPostInfoVO vo = new SocPostInfoVO();
//        封装发帖者头像，用户名，帖子文件信息
        SocPostItemVO itemVO = getSocPostItemVOBySoPost(byId);
        BeanUtils.copyProperties(itemVO, vo);
//        获取评论数据,评论文件信息
        PageDTO<SocPostRepliesVO> socRepliesVOPage = getSocRepliesVOPage(query);
        vo.setReplies(socRepliesVOPage);
//        是否点赞
        try {
            vo.setIsLiked(postLikesService.isLike(query.getPostId(), UserContext.getUser()));
        } catch (LoginUserException ignored) {
        }
        ForumUserVO userInfo = getUserInfo(vo.getUserId());
        vo.setUserInfo(userInfo);
        return vo;
    }

    public SocPostItemVO getSocPostItemVOBySoPost(SocPost socPost) {
        SocPostItemVO vo = new SocPostItemVO();
        BeanUtils.copyProperties(socPost, vo);
        R<UserInfo> fR = frontClient.getFroUserInfoById(vo.getUserId());
        UserInfo user = fR.getData();
        vo.setAvatar(user.getAvatar());
        vo.setNickname(user.getNickname());
        //        获取关联标签
        List<SocPostTagRelations> tags = postTagService.getListByPostId(socPost.getPostId());
        if (CollUtil.isNotEmpty(tags)){
            List<Integer> collect = tags.stream().map(SocPostTagRelations::getTagId).collect(Collectors.toList());
            List<SocPostTags> list = tagsService.lambdaQuery().in(SocPostTags::getTagId, collect).list();
            vo.setTags(list);
        }
        List<SocPostFile> files = postFileService.getListByPostId(vo.getPostId());
        Long likes = postLikesService.countByPostId(vo.getPostId());
        Long remarks = socPostRepliesService.countByPostId(vo.getPostId());
        try {
            boolean b = postLikesService.isLike(vo.getPostId(), UserContext.getUser());
            vo.setIsLike(b);
        } catch (LoginUserException ignored) {
            vo.setIsLike(false);
        }
        vo.setLikes(likes);
        vo.setRemarks(remarks);
        vo.setFiles(files);
        return vo;
    }

    @Override
    public PageDTO<SocPostRepliesVO> getSocRepliesVOPage(PostRepliesQuery query) {
        PageDTO<SocPostRepliesVO> pageDTO = MpPageUtil.of(socPostRepliesService.getSocRepliesPage(query), SocPostRepliesVO.class);
//        封装评论上传的文件信息
        if (CollUtil.isNotEmpty(pageDTO.getList())) {
            pageDTO.getList().forEach(item -> {
                List<SocPostRepliesFile> list = postRepliesFileService.listByReplyId(item.getReplyId());
                UserInfo user = frontClient.getFroUserInfoById(String.valueOf(item.getUserId())).getData();
                item.setNickname(user.getNickname());
                item.setAvatar(user.getAvatar());
                item.setFiles(list);
            });
        }
        return pageDTO;
    }

    @Override
    public void addSocPostReply(SocPostReplyDTO socPostReplies) {
        socPostReplies.setUserId(Integer.valueOf(UserContext.getUser()));
        socPostReplies.setCreateTime(new Date());
        socPostRepliesService.addSocPostReply(socPostReplies);
        if (CollUtil.isNotEmpty(socPostReplies.getFiles())) {
            socPostReplies.getFiles().forEach(item -> {
                item.setPostReplyId(socPostReplies.getReplyId());
                postRepliesFileService.save(item);
            });
        }
    }

    @Override
    public ForumUserVO getUserInfo(String userId) {
        R<UserInfo> froUserInfoById = frontClient.getFroUserInfoById(userId);
        UserInfo data = froUserInfoById.getData();
        if (ObjUtil.isEmpty(data)) {
            return null;
        }
        UserForumProfiles byUserId = userForumProfilesService.getByUserId(Integer.valueOf(userId));
        if (byUserId==null){
            return null;
        }
        ForumUserVO postUserInfoVO = new ForumUserVO();
        BeanUtils.copyProperties(data, postUserInfoVO);
        BeanUtils.copyProperties(byUserId, postUserInfoVO);
//        关注的吧
        postUserInfoVO.setFollowBards(getFollowBardByUserId(userId));
//        用户发布的帖子
        postUserInfoVO.setPublishPosts(postService.getUserPostList(userId));
        return postUserInfoVO;
    }

    @Override
    public SocBardVO getBardInfoByPostId(String postId) {
        SocPost byId = postService.getById(postId);
        if (byId != null) {
            return getBardInfoById(byId.getBardId());
        }
        return null;
    }

    @Override
    public SocBardVO getBardInfoById(String bardId) {
        SocBard bard = bardService.getBardInfoById(bardId);
        SocBardVO socBardVO = new SocBardVO();
        BeanUtils.copyProperties(bard, socBardVO);
        Long count = bardFollowService.getFollowerCountByBardId(bardId);
        socBardVO.setFollowerCount(count);
        Long postCount = postService.getPostCountByBardId(bardId);
        socBardVO.setPostCount(postCount);
        try {
            boolean b = bardFollowService.isFollow(bardId, UserContext.getUser());
            socBardVO.setIsFollow(b);
        } catch (LoginUserException ignored) {
            socBardVO.setIsFollow(false);
        }
        return socBardVO;
    }

    @Override
    public PageDTO<SocBardVO> getBardVoPage(BardQuery query) {
        PageDTO<SocBard> bardPage = bardService.getBardPage(query);
        PageDTO<SocBardVO> of = PageUtil.of(bardPage, SocBardVO.class);
//        获取想详细信息
        List<SocBardVO> collect = of.getList().stream().map(item -> getBardInfoById(item.getBardId().toString())).collect(Collectors.toList());
        of.setList(collect);
        return of;
    }

    @Override
    public PageDTO<ForumUserVO> getForumUserInfoPage(UserForumQuery query) {
        String sortBy = query.getSortBy();
        String bardId = query.getBardId();
        LambdaQueryWrapper<UserForumProfiles> wrapper = new LambdaQueryWrapper<>();
        if (StrUtil.isNotBlank(bardId)){
            List<SocBardFollow> userListByBardId = bardFollowService.getUserListByBardId(bardId);
            if (CollUtil.isEmpty(userListByBardId)){
                return PageDTO.emptyPage();
            }
            List<Integer> collect = userListByBardId.stream().map(SocBardFollow::getUserId).collect(Collectors.toList());
            wrapper.in(UserForumProfiles::getUserId,collect);
        }
        wrapper.orderBy("like".equals(sortBy), query.getIsAsc(), UserForumProfiles::getLikeCount)
                .orderBy("post".equals(sortBy), query.getIsAsc(), UserForumProfiles::getPostCount);
        Page<UserForumProfiles> page = userForumProfilesService.page(query.toMpPage(), wrapper);
        PageDTO<ForumUserVO> of = MpPageUtil.of(page, ForumUserVO.class);
        List<ForumUserVO> collect = of.getList().stream().map(item -> getUserInfo(item.getUserId().toString())).collect(Collectors.toList());
        of.setList(collect);
        return of;
    }

    /**
     * 获取用户关注的贴吧列表
     *
     * @param userId
     * @return {@link List }<{@link SocBard }>
     */
    @Override
    public List<SocBardVO> getFollowBardByUserId(String userId) {
        List<Integer> followBardByUserId = bardFollowService.getFollowBardByUserId(userId);
        if (CollUtil.isNotEmpty(followBardByUserId)) {
            List<SocBard> socBards = bardService.listByIds(followBardByUserId);
            return socBards.stream().map(item -> getBardInfoById(item.getBardId().toString())).collect(Collectors.toList());
        }
        return null;
    }

    @Override
    public void followBard(SocBardFollow socBardFollow) {
        bardFollowService.save(socBardFollow);
        UserForumProfiles byUserId = userForumProfilesService.getByUserId(socBardFollow.getUserId());
        byUserId.setFollowCount(byUserId.getFollowCount() + 1);
        userForumProfilesService.updateById(byUserId);
    }

    @Override
    public void deleteFollow(SocBardFollow socBardFollow) {
        bardFollowService.deleteFollow(socBardFollow);
        UserForumProfiles byUserId = userForumProfilesService.getByUserId(socBardFollow.getUserId());
        byUserId.setFollowCount(byUserId.getFollowCount() - 1);
        userForumProfilesService.updateById(byUserId);
    }
}
